using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;

namespace Sensor.UI.Utils;

/// <summary>
/// 高性能环形缓冲区，用于高并发场景下的数据存储
/// </summary>
/// <typeparam name="T">存储的数据类型</typeparam>
public class RingBuffer<T> where T : class
{
    private readonly T[] _buffer;
    private readonly int _capacity;
    private int _head = 0; // 写入位置
    private int _tail = 0; // 读取位置
    private int _count = 0; // 当前元素数量
    private readonly object _lock = new();

    public int Count => _count;
    public bool IsEmpty => _count == 0;
    public bool IsFull => _count == _capacity;

    public RingBuffer(int capacity)
    {
        if (capacity <= 0)
            throw new ArgumentException("Capacity must be greater than 0", nameof(capacity));
        
        _capacity = capacity;
        _buffer = new T[capacity];
    }

    /// <summary>
    /// 尝试添加元素，如果缓冲区已满则覆盖最旧的元素
    /// </summary>
    /// <param name="item">要添加的元素</param>
    /// <returns>是否覆盖了旧元素</returns>
    public bool TryAdd(T item)
    {
        if (item == null)
            throw new ArgumentNullException(nameof(item));

        lock (_lock)
        {
            bool overwritten = IsFull;
            
            _buffer[_head] = item;
            _head = (_head + 1) % _capacity;
            
            if (IsFull)
            {
                _tail = (_tail + 1) % _capacity; // 覆盖最旧元素
            }
            else
            {
                _count++;
            }
            
            return overwritten;
        }
    }

    /// <summary>
    /// 尝试获取元素
    /// </summary>
    /// <param name="item">获取到的元素</param>
    /// <returns>是否成功获取</returns>
    public bool TryTake(out T item)
    {
        lock (_lock)
        {
            if (IsEmpty)
            {
                item = default!;
                return false;
            }

            item = _buffer[_tail];
            _buffer[_tail] = default!; // 清除引用，帮助GC
            _tail = (_tail + 1) % _capacity;
            _count--;
            
            return true;
        }
    }

    /// <summary>
    /// 尝试批量获取元素
    /// </summary>
    /// <param name="items">目标数组</param>
    /// <param name="count">实际获取的元素数量</param>
    /// <returns>是否成功获取任何元素</returns>
    public bool TryTakeRange(T[] items, out int count)
    {
        if (items == null)
            throw new ArgumentNullException(nameof(items));

        lock (_lock)
        {
            if (IsEmpty)
            {
                count = 0;
                return false;
            }

            count = Math.Min(_count, items.Length);
            for (int i = 0; i < count; i++)
            {
                items[i] = _buffer[_tail];
                _buffer[_tail] = default!; // 清除引用，帮助GC
                _tail = (_tail + 1) % _capacity;
            }
            
            _count -= count;
            return count > 0;
        }
    }

    /// <summary>
    /// 清空缓冲区
    /// </summary>
    public void Clear()
    {
        lock (_lock)
        {
            Array.Clear(_buffer, 0, _buffer.Length);
            _head = 0;
            _tail = 0;
            _count = 0;
        }
    }
}